import { requestTimeout, serviceConfig, ServiceType } from '@/config'
import { responseCode, responseMessage, responseHandlerMap } from '@/config/response-code'
import { useNotification } from '@/composables/useNotification'
import { useAuthStore } from '@/stores/modules/auth'

import { useRouter } from 'vue-router'
import type { BaseResponse } from '@/types/response'
import type { RequestOptions, RequestParams } from '@/types/request'

const notification = useNotification()

// 请求方法枚举
enum HttpMethod {
  GET = 'GET',
  POST = 'POST',
  PUT = 'PUT',
  DELETE = 'DELETE',
  PATCH = 'PATCH',
}

// 基础配置
const DEFAULT_OPTIONS: Partial<RequestOptions> = {
  mode: 'cors',
  credentials: 'include',
  headers: new Headers({
    'Content-Type': 'application/json',
  }),
  redirect: 'follow',
  needAuth: true, // 默认需要认证头
}

// 判断是否使用网关
const useGateway = !!serviceConfig.gateway

// 获取API前缀
const getApiPrefix = (service?: ServiceType) => {
  if (!service) return '/api'
  return `/api/${service}`
}

// 获取服务地址
const getServiceUrl = (service?: ServiceType) => {
  if (useGateway) {
    if (!service) return `${serviceConfig.gateway}/${serviceConfig.default}`
    return `${serviceConfig.gateway}/${serviceConfig[service]}`
  }
  // 开发环境使用代理
  return getApiPrefix(service)
}

// 统一的错误处理
const errorHandler = (error: Error & { code?: string }, skipErrorHandler?: boolean) => {
  if (skipErrorHandler) return Promise.reject(error)

  const router = useRouter()

  // 如果是业务错误码
  if (error.code && error.code in responseHandlerMap) {
    const handler = responseHandlerMap[error.code as keyof typeof responseHandlerMap]

    // 显示错误消息
    if (handler?.message) {
      notification.error(error.message || handler.message, {
        title: '错误',
      })
    }

    // 处理重定向
    if (handler?.redirect) {
      router.push(handler.redirect)
    }

    // 执行自定义处理函数
    if (handler?.handler) {
      handler.handler()
    }
  }

  return Promise.reject(error)
}

// 处理响应
const handleResponse = async <T>(response: Response, returnBaseResponse?: boolean): Promise<T> => {
  if (!response.ok) {
    throw new Error(responseMessage.networkError)
  }

  const json: BaseResponse<T> = await response.json()
  if (returnBaseResponse) {
    return json as T
  }
  if (!json.success || json.code !== responseCode.success) {
    const error = new Error(json.message || responseMessage.default) as Error & { code?: string }
    error.code = json.code
    throw error
  }
  return json.data
}

/** 构建URL */
const buildURL = (url: string, params?: RequestParams, serviceType?: ServiceType): string => {
  // 获取服务基础地址
  const baseUrl = getServiceUrl(serviceType)

  // 构建完整URL
  let finalUrl = `${baseUrl}${url.startsWith('/') ? url : `/${url}`}`

  if (params) {
    const queryString = Object.entries(params)
      .filter(([, value]) => value != null)
      .map(([key, value]) => `${key}=${encodeURIComponent(String(value))}`)
      .join('&')

    if (queryString) {
      finalUrl += finalUrl.includes('?') ? `&${queryString}` : `?${queryString}`
    }
  }

  return finalUrl
}

// 修改基础请求方法的参数
const baseFetch = async <T>(
  url: string,
  options: RequestOptions & { serviceType?: ServiceType },
): Promise<T> => {
  const {
    params,
    body,
    skipErrorHandler,
    returnBaseResponse,
    abortSignal,
    needAuth,
    customHeaders,
    serviceType, // 完全可选
    ...fetchOptions
  } = options

  // 创建新的 headers
  const headers = new Headers(fetchOptions.headers || DEFAULT_OPTIONS.headers)

  // 处理认证头
  if (needAuth !== false) {
    // 只有明确设置 false 才不添加认证头
    const authStore = useAuthStore()
    if (authStore.userInfo?.tokenInfo) {
      headers.set(authStore.userInfo.tokenInfo.tokenName, authStore.userInfo.tokenInfo.tokenValue)
    }
  }

  // 处理自定义头
  if (customHeaders) {
    Object.entries(customHeaders).forEach(([key, value]) => {
      headers.set(key, value)
    })
  }

  const finalOptions: RequestInit = {
    ...DEFAULT_OPTIONS,
    ...fetchOptions,
    headers,
    signal: abortSignal,
    body:
      body instanceof FormData || body instanceof URLSearchParams || typeof body === 'string'
        ? body
        : body
          ? JSON.stringify(body)
          : null,
  }

  // 如果是 FormData，删除 Content-Type 让浏览器自动设置
  if (body instanceof FormData) {
    const headers = new Headers(finalOptions.headers)
    headers.delete('Content-Type')
    finalOptions.headers = headers
  }

  try {
    const response = (await Promise.race([
      fetch(buildURL(url, params, serviceType), finalOptions),
      new Promise((_, reject) => {
        setTimeout(() => reject(new Error('请求超时')), requestTimeout)
      }),
    ])) as Response

    return await handleResponse<T>(response, returnBaseResponse)
  } catch (error) {
    return errorHandler(error as Error, skipErrorHandler)
  }
}

// 导出请求方法时添加serviceType参数
export const request = {
  get: <T>(
    url: string,
    options: Omit<RequestOptions & { serviceType?: ServiceType }, 'body' | 'method'> = {},
  ) => baseFetch<T>(url, { ...options, method: HttpMethod.GET }),

  post: <T>(
    url: string,
    options: Omit<RequestOptions & { serviceType?: ServiceType }, 'method'> = {},
  ) => baseFetch<T>(url, { ...options, method: HttpMethod.POST }),

  put: <T>(
    url: string,
    options: Omit<RequestOptions & { serviceType?: ServiceType }, 'method'> = {},
  ) => baseFetch<T>(url, { ...options, method: HttpMethod.PUT }),

  delete: <T>(
    url: string,
    options: Omit<RequestOptions & { serviceType?: ServiceType }, 'body' | 'method'> = {},
  ) => baseFetch<T>(url, { ...options, method: HttpMethod.DELETE }),

  patch: <T>(
    url: string,
    options: Omit<RequestOptions & { serviceType?: ServiceType }, 'method'> = {},
  ) => baseFetch<T>(url, { ...options, method: HttpMethod.PATCH }),
}

// 创建取消请求的控制器
export const createAbortController = () => new AbortController()
